package com.yang.service.Impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yang.domain.DTO.AddArticleDto;
import com.yang.domain.DTO.EditArticleDto;
import com.yang.domain.Result;
import com.yang.domain.VO.*;
import com.yang.domain.entity.Article;
import com.yang.domain.entity.ArticleTag;
import com.yang.domain.entity.Category;
import com.yang.mapper.ArticleMapper;
import com.yang.service.ArticleService;
import com.yang.service.ArticleTagService;
import com.yang.service.CategoryService;
import com.yang.utils.BeanCopyUtils;
import com.yang.utils.RedisCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.yang.constants.RedisConstants.ARTICLE_VIEWCOUNT;
import static com.yang.constants.SystemConstants.ARTICLE_STATUS_NORMAL;


/**
 * <p>
 * 文章服务层实现类
 * </p>
 * @author yang
 * @date 2023/5/29
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {


    @Resource
    private CategoryService categoryService;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ArticleTagService articleTagService;

    @Override
    public Result hotArticleList() {

        //查询热门文章 封装成ResponseResult返回
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        //必须是正式文章
        queryWrapper.eq(Article::getStatus,ARTICLE_STATUS_NORMAL);
        //按照浏览量进行排序
        queryWrapper.orderByDesc(Article::getViewCount);
        //最多只查询10条
        Page<Article> page = new Page<>(1,10);

        page(page,queryWrapper);

        List<Article> articles = page.getRecords();

        //3.Article-->HotArticleVo
        List<HotArticleVo> articleVos = BeanCopyUtils.copyBeanList(articles, HotArticleVo.class);


        return Result.okResult(articleVos);
    }

    /**
     * 分页查询文章列表
     * 首页：分页查询所有文章
     * 分类：在分类里面查询对应的分类文章
     */
    @Override
    public Result articleList(Integer pageNum, Integer pageSize, Long categoryId) {
        //1.拿到查询条件
        LambdaQueryWrapper<Article> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        //2.根据categoryId是否存在，来执行不同的查询逻辑,并且发布装配是正常的，然后把置顶的文章置顶
        lambdaQueryWrapper
                .eq(Objects.nonNull(categoryId) && categoryId>0 ,Article::getCategoryId,categoryId)
                .eq(Article::getStatus,ARTICLE_STATUS_NORMAL)
                .orderByDesc(Article::getIsTop);

        //3.封装查询条件进行分页查询
        Page<Article> page = new Page<>(pageNum,pageSize);
        page(page,lambdaQueryWrapper);

        //4.拿到分页查询的数据
        List<Article> articleList = page.getRecords();

        //5.查询出分页的名字重新进行封装，因为在前端中需要分类名字，但是我们只有分类id
        articleList = articleList.stream()
                .map(article -> article.setCategoryName(categoryService.getById(article.getCategoryId())
                                .getName())).collect(Collectors.toList());

        //6.articleList-->ArticleListVo
        List<ArticleListVo> articleListVos = BeanCopyUtils.copyBeanList(articleList, ArticleListVo.class);

        //7.articleListVos-->pageVo，包含数据和total
        PageVo pageVo = new PageVo(articleListVos,page.getTotal());

        return Result.okResult(pageVo);
    }

    @Override
    public Result getArticleDetail(Long id) {
        //1.根据id查询博客详细信息
        Article article = getById(id);
        Integer viewCount = redisCache.getCacheMapValue(ARTICLE_VIEWCOUNT, id.toString());
        article.setViewCount(viewCount.longValue());

        //2.article-->articleDetailVo
        ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class);

        //3.查询博客所属的分类
        Category category = categoryService.getById(articleDetailVo.getCategoryId());

        //4.进行分类封装
        if (category!=null){
            articleDetailVo.setCategoryName(category.getName());
        }

        //5.返回文章信息
        return Result.okResult(articleDetailVo);
    }

    @Override
    public Result updateViewCount(Long id) {
        //第二步.更新游览量去更新redis的数据
        redisCache.incrementCacheMapValue(ARTICLE_VIEWCOUNT,id.toString(),1);

        return Result.okResult();
    }

    @Override
    public Result addAddArticl(AddArticleDto addArticleDto) {
        //1.新增博客
        Article article = BeanCopyUtils.copyBean(addArticleDto, Article.class);
        save(article);

        //2.拿到addArticleDto中所有的tagId
        List<ArticleTag> articleTags = addArticleDto.getTags()
                                                    .stream()
                                                    .map(tagId -> new ArticleTag(article.getId(), tagId))
                                                    .collect(Collectors.toList());

        //3.新增博客标签关联表信息
        articleTagService.saveBatch(articleTags);

        //4.返回
        return Result.okResult();
    }

    @Override
    public Result findAllAddArticle(Article article, Integer pageNum, Integer pageSize) {

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();

        //1.根据标题和摘要进行模糊查询
        wrapper.like(StringUtils.hasText(article.getTitle()),Article::getTitle,article.getTitle());
        wrapper.like(StringUtils.hasText(article.getSummary()),Article::getSummary,article.getSummary());
        //2.不能把删除了的文章查询出来
        wrapper.eq(Article::getDelFlag,0);

        Page<Article> page = new Page<>(pageNum,pageSize);
        page(page,wrapper);

        List<Article> articles = page.getRecords();

        //3.封装成VO类
        PageVo pageVo = new PageVo();
        pageVo.setTotal(page.getTotal());
        pageVo.setRows(articles);

        return Result.okResult(pageVo);
    }

    @Override
    @Transactional
    public Result edit(EditArticleDto articleDto) {
        //1.先更新文章博客表
        Article article = BeanCopyUtils.copyBean(articleDto, Article.class);
        updateById(article);



        //2.先删除文章所关联的表信息
        LambdaQueryWrapper<ArticleTag> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ArticleTag::getArticleId,articleDto.getId());
        articleTagService.remove(wrapper);

        //3.重新添加标签信息
        List<ArticleTag> articleTags = articleDto.getTags()
                                                 .stream()
                                                 .map(tagId -> new ArticleTag(articleDto.getId(), tagId))
                                                 .collect(Collectors.toList());


        articleTagService.saveBatch(articleTags);

        return Result.okResult();
    }

    @Override
    public ArticleVo getInfo(Long articleId) {
        //1.根据id查询文章详细信息
        Article article = getById(articleId);

        //2.根据文章信息文章标签关联表
        LambdaQueryWrapper<ArticleTag> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ArticleTag::getArticleId,articleId);

        List<Long> tagIds = articleTagService.list(wrapper)
                                             .stream()
                                             .map(ArticleTag::getTagId)
                                             .collect(Collectors.toList());

        //3.封装为ArticleVo类
        ArticleVo articleVo = BeanCopyUtils.copyBean(article, ArticleVo.class);
        articleVo.setTags(tagIds);

        return articleVo;
    }


}
